#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Cinta.h"
#include "error.h"

struct celda
{
	Tuple el;
	aList tl;
};

struct sCinta
{
	struct celda cd;
	aList ppd;
	Bool arr;
};

aList
aList_vacia (void)
{
	return NULL;
}

aList
aList_destroy (aList l)
{
	aList aux = NULL;
	aux = l;
	while (aux!=NULL)
	{
		aux = l -> tl;
		tuple_destroy (l -> el);
		l -> tl = aList_vacia ();
		free( l);
		l = aux;
	}
	return NULL;
}

Cinta
cinta_create (aList l)
{
	Cinta c=NULL;
	c = (Cinta) calloc (1,sizeof(struct sCinta));
	if (c==NULL)
	{
		warn(ERRFMT,"cinta_create : Hubo un error al crear la cinta\n",__LINE__);
		return c;
	}
	c -> ppd = aList_vacia ();
	(c -> cd).el = NULL; 
	(c -> cd).tl = l;
	c -> arr = FALSE;

	return c;
}

void
cinta_arr (Cinta c)
{
	assert (c!=NULL);

	c -> ppd = &(c -> cd);

	c -> arr = TRUE;
}

Bool
cinta_fin (Cinta c)
{
	if ((c -> arr)!= TRUE)	/* ERROR 1 */
	{
		printf("La cinta no esta arrancada!\n");
		assert ((c -> arr)==TRUE);
	}
	return (c -> ppd -> tl== NULL);
}

void
cinta_av (Cinta c)
{
	Bool b;
	b = cinta_fin(c);

	if (b)			/* ERROR 1 */
	{
		printf("Estamos al final(Desde cinta_av)\n");
		assert(!b);
	}

	c -> ppd = c -> ppd -> tl;
}

Tuple
cinta_elec (Cinta c)
{
	Bool b;
	b = cinta_fin(c);

	if (b)			/* ERROR 1 */
	{
		printf("Estamos al final(desde cinta_elec)\n");
		return NULL;
		/*assert(!b);*/
	}

	return c -> ppd -> tl -> el;
}

/*	INSERCI�N  ORDENADA */
void
cinta_ins (Cinta c, Tuple t)
{
	aList new = aList_vacia();
	Key k1=NULL,k2=NULL;
	Bool b = FALSE;
	
	new = (aList) calloc (1,sizeof(struct celda));
	assert (new !=NULL);
	
	cinta_arr(c);
	if(!(cinta_fin(c)))
	{
		k2 = tuple_fst(t);
		k1=tuple_fst(c -> ppd -> tl -> el);
		while (!(cinta_fin(c)) && b)
		{
			key_destroy(k1);
			k1=tuple_fst(c -> ppd -> tl -> el);
			b =key_le(k1,k2);
			if (b)
			{
				cinta_av(c);
			}
		}
		key_destroy(k1);
		key_destroy(k2);
	}
	new -> el = tuple_clone (t);
	new -> tl = c -> ppd -> tl;
	c -> ppd -> tl = new;
}


		/*	INSERCI�N  NO  ORDENADA		*/
/*void
cinta_ins (Cinta c, Tuple t)
{
	aList new= aList_vacia ();

	if ((c -> arr)!=TRUE)
	{
		printf("La cinta no esta arrancada!\n");
		assert ((c -> arr)==TRUE);
	}

	new = (aList) calloc (1,sizeof(struct celda));
	assert (new !=NULL);

	new -> el = tuple_clone (t);
	new -> tl = c -> ppd -> tl;
	c -> ppd -> tl = new;
}
*/
void
cinta_del (Cinta c)
{/* DESC: Borra el elemento corriente. */
	aList aux= aList_vacia ();

	if (cinta_fin(c))			/* ERROR 1 */
	{
		printf("Estamos al final\n");
		assert(!cinta_fin(c));
	}

	aux = c -> ppd -> tl -> tl;
	tuple_destroy(c -> ppd -> tl -> el);
	free(c -> ppd -> tl);/*cuidado!*/
	c -> ppd -> tl = aux;
}

aList
cinta_destroy (Cinta c)
{/*	PRE: { Pi(c) = L1 /\ Pd(c) = L2 }
	POS: { l = Pi(c)++ Pd(c) }   */
	aList aux = (c -> cd).tl;

	(c -> cd).tl = NULL;
	c -> ppd = NULL;
	free(c);
	c = NULL;

	return aux;
}
